I think the article to which the linked article is responding is a bit of a broken clock... that is, it's correct about operator overloading being detrimental, but their reasoning is incorrect.
The questions about allocation and garbage collection are irrelevant for the reasons you mention. But operator overloading allows problematic code for another reason.
`AddMatrices` is unambiguous; clearly its operands should be matrices, and they should be added according to matrix arithmetic rules (and, like you said, if the underlying code is buggy, it would also be buggy as an overloaded operator). The problem is that `+` is ambiguous. And if you're dealing with matrices, you're probably looking at code written by a math person, meaning it's going to be shorthand-heavy and the operands' names are unlikely to make the variables' types clear.
But at least in the matrix vs. scalar case, you have a similar set of axioms, so changing `x + m` to `m + x` should not alter the result regardless of the types. This is not so when people shove even more meanings onto a single operator, like `+` for string concat. String concatenation doesn't commute. Furthermore, different languages have different rules for "adding" one string and one number, so it causes needless friction for polyglots.
I'm not saying I prefer `concat(s1, s2)`, because I like my operators. I'm saying I prefer something like Raku's `~`. As an added bonus, you get automatic and consistent coercions. You know exactly what the operation is and how the operands will be treated when you see `~`, with no need to find the operand types.
In conclusion, operator overloading is a half-assing of full-fledged user-defined operators, and it encourages programmers to shove disparate functionalities (often with different axioms) into the same operator. Either let people write traditional functions, or give them the ability to create their own operators so they're not tempted to make a mess of the default set of operators.