It is because `Attributes` have `UpValues` associated with them so at the end you are not trying to `Set` to `Attributes[Foo]` but it will be translated. 

You can mimic that with e.g. `UpSetDelayed (^:=)`:

 ClearAll[f]

 Set[f[x_], attr_] ^:= SetAttributes[x, attr];

 SetAttributes[f, {Protected, HoldFirst}]


----------


 f = 2
> Set::wrsym: Symbol f is Protected. >>

 f[x] = HoldFirst (*no error*)

 Attributes[x]
> {HoldFirst}