I think this depends upon the language intrinsic support for vectors/vector operations. I would (generally) prefer to specify operations using a simpler, more concise syntax, and have the compiler map that into the hardware. The problem with this is, most compilers don't do such a good job with that.
I like the Matrix/vector operations by default for the reason that it becomes quite a bit simpler to understand the written code. Expressing things the way Numpy forces you to, means that you have to reason about the interface of your code to Numpy, as well as how Numpy will operate.
For matrix mult, I agree, writing out loops is tedious. This is why things like M = A * B, where M, A, B are all matrices, is far, far better than writing out the loop representation. I agree as well, messing up the index ordering is annoying (and I still do this 30+ years onward with Fortran, C, etc.)
Julia makes this stuff easy to trivial. It makes the interface to using this capability easy to trivial. It makes for good overall performance (I rarely run codes only once).