These commands let every armor stand in a 200x200 area around a player rotate their head to the player with 90° precision (condition: it is looking at positive z):
Initialization:
scoreboard objectives add rotation dummy
Loop:
scoreboard players set @e[type=armor_stand,tag=!rotation] rotation 0
scoreboard players tag @e[type=armor_stand,tag=!rotation] add rotation
execute @p ~1 ~ ~-1 entitydata @e[type=armor_stand,y=0,dx=100,dy=256,dz=-100,score_rotation_min=1] {Pose:{Head:[0f,45f,0f]}}
execute @p ~1 ~ ~1 entitydata @e[type=armor_stand,y=0,dx=100,dy=256,dz=100,score_rotation=0] {Pose:{Head:[0f,135f,0f]}}
execute @p ~1 ~ ~1 entitydata @e[type=armor_stand,y=0,dx=100,dy=256,dz=100,score_rotation_min=2] {Pose:{Head:[0f,135f,0f]}}
execute @p ~-1 ~ ~1 entitydata @e[type=armor_stand,y=0,dx=-100,dy=256,dz=100,score_rotation=1] {Pose:{Head:[0f,225f,0f]}}
execute @p ~-1 ~ ~1 entitydata @e[type=armor_stand,y=0,dx=-100,dy=256,dz=100,score_rotation_min=3] {Pose:{Head:[0f,225f,0f]}}
execute @p ~-1 ~ ~-1 entitydata @e[type=armor_stand,y=0,dx=-100,dy=256,dz=-100,score_rotation=2] {Pose:{Head:[0f,315f,0f]}}
execute @p ~1 ~ ~-1 scoreboard players set @e[type=armor_stand,y=0,dx=100,dy=256,dz=-100,score_rotation_min=1] rotation 0
execute @p ~1 ~ ~1 scoreboard players set @e[type=armor_stand,y=0,dx=100,dy=256,dz=100,score_rotation=0] rotation 1
execute @p ~1 ~ ~1 scoreboard players set @e[type=armor_stand,y=0,dx=100,dy=256,dz=100,score_rotation_min=2] rotation 1
execute @p ~-1 ~ ~1 scoreboard players set @e[type=armor_stand,y=0,dx=-100,dy=256,dz=100,score_rotation=1] rotation 2
execute @p ~-1 ~ ~1 scoreboard players set @e[type=armor_stand,y=0,dx=-100,dy=256,dz=100,score_rotation_min=3] rotation 2
execute @p ~-1 ~ ~-1 scoreboard players set @e[type=armor_stand,y=0,dx=-100,dy=256,dz=-100,score_rotation=2] rotation 3
This rotates the armor stands to your quadrant and then assigns a scoreboard value to them so that they don't keep rotating to you every tick (would create more lag). Instead of executing everything from the armor stand I noticed that it's way easier to execute everything from the player. Usually I try to make my command stuff multiplayer compatible, but here I use @p, because the only good solution if one armor stand is supposed to look at two people in different directions would be to select the closest one. That would require to execute everything from the armor stand again, which complicates things and requires more tags/scoreboards. If you need that, tell me, but this system here works very well for one player. Selecting smaller ranges than 90° would be much more complicated. Here I profit from the dx dy dz selectors that select a rectangle, so I just check a rectangle far into the positive x and z direction, one far into the postitive x+negative z direction and so on and find an armor stand there. To avoid buggyness, I had to make it so that the armor stand ignores you if you're exactly on the same x or z value as it. But in that case there won't be a good direction for it to rotate to, so it doesn't really matter. I could add special cases for that, but it doesn't make it much better and complicates the commands that are already there.
...and just before sending I noticed that this all breaks if you don't add a value to the rotation score in the beginning, so I added the first two commands. They will only execute once for every armor stand.
If you have any more questions to how this works, ask in the comments and I can explain. It was a fun challenge!