IMO, doing matrix operations by default is the mathematically correct thing to do. E.g. having exp(M::Matrix) give anything other than the matrix exponential is insanity. Same with A::Matrix * B::Matrix giving anything other than matrix multiplication.
As far as the ‘.’ for elementwise operations, I don’t think it’s that hard to miss, but I guess my eyes are trained for it by now.
There’s also an @. macro to make an entire expression element wise though if needed, e.g.
@. h(f(x) + g(y))
is equivalent to h.(f.(x) .+ g.(y))
I think this broadcasting machinery is one of the closet parts of julia because you get to choose at the call site if you want the function to apply element-wise or to see the whole array, and it works on any container, with user customizable behaviour for user defined containers, and has all sorts of goodies like automatic loop fusion.