The obvious answer is the one that John and a couple other people gave, namely:
>>> names = [name for name in names if name[-5:] != "Smith"] # <-- slower
But that has the disadvantage that it creates a new list object, rather than reusing the original object. I did some profiling and experimentation, and the most efficient method I came up with is:
>>> names[:] = (name for name in names if name[-5:] != "Smith") # <-- faster
Assigning to "names[:]" basically means "replace the contents of the names list with the following value". It's different from just assigning to names, in that it doesn't create a new list object. The right hand side of the assignment is a generator expression (note the use of parentheses rather than square brackets). This will cause Python to iterate across the list.
Some quick profiling suggests that this is about 30% faster than the list comprehension approach, and about 40% faster than the filter approach.
Caveat: while this solution is faster than the obvious solution, it is more obscure, and relies on more advanced Python techniques. If you do use it, I recommend accompanying it with a comment. It's probably only worth using in cases where you really care about the performance of this particular operation (which is pretty fast no matter what). (In the case where I used this, I was doing A* beam search, and used this to remove search points from the search beam.)