Re: "the ability to use operators on generic types."
The alternative, in a lot of use cases, to using generics, is to have multiple versions of the same code, for example, once for each type that needs it. Repeated code is definitely a code smell.
For example, take the List class. Would you rather the language had a List<T>, with one implementation, or one class for every built-in type, such as ListOfInt, ListOfFloat, ListOfString. What about if you want a list of lists? Does the language need to define ListOfListOfInt rather than just allowing you to use List<List<int>>? What about if you want to have a list of your own classes, Foo and Bar, do you want to have to write the boilerplate code yourself for ListOfFoo and ListOfBar? It's a no-brainer that the List<T> class is defined once, has one implementation, and behaves in the the same way whichever T you use it with.
Generics are a powerful, and pretty obviously needed, tool in the programmer's arsenal. I think you may be making the mistake of thinking that they somehow erode type safety, but if you were going to try to add a string to a list of integers, you'd get a compile error. Whilst the definition of List<T> might be generic, the implementation in the consuming code which might use List<int> very much is not.
On the other hand, if you were to use a List<dynamic>, to circumvent the compiler's type checking, then you need your head boiled.