When you use quotes around an array parameter, joining happens first, so before the :# operation (or any other expansion operation). The (@) forces the :# operation to work on the array elements and only then join the result.
Actually that last part is wrong. The (@) cancels the joining. "${(M@)array:#pattern}" returns multiple strings if "array" contains multiple elements that match "pattern". If instead you need a single string, you can force the joining with either "${(j: :M@)array:#pattern}" or "${${(M@)array:#pattern}}".
Philippe