Well, as I understand, the clue you seek is actually inside the Attributes function. Or, more precisely, in the Attributes of the Attributes function. A line like
Attributes[Attributes]
returns a list
{HoldAll, Listable, Protected}
HoldAll attribute means that a function with this attribute does not perform any trasformations of the input arguments and "looks" at them just like you do. So, when you write Attributes[names[[3220]]] WL does not evaluate names[[3220]] and the Attributes function "sees" only the internal representation of names[[3220]] that is Part[names, 3220]. And the Head of this expression is Part, not something from Symbol, String or HoldPattern.
However, you can force Wolfram Language to evaluate the input of any function by calling the Evaluate function. Try running the following:
Attributes[Evaluate[names[[3220]]]]