This is a fairly natural question and I feel it is worthy of attention. I am going to answer in two parts. First, I am going to show a method that is more appropriate for Mathematica programming and which I recommend you use instead. Then I will show how to force the action you are attempting.
A Better Alternative
The normal way to accomplish programmatically selected assignments is to use indexed variables. This allows you to assemble a "variable" from inert parts. For example, one would use a single variable var and simply make assignments (SeedRandom[1] for a consistent result):
SeedRandom[1]
Do[
var[i] = RandomInteger[9],
{i, {1, 2, 3, 2, 3, 1, 3}}
]
Or recall them:
var /@ {1, 2, 3}
{0, 7, 8}
If you desire a certain name be attached to a value you can index with Strings.
names = {"aaa", "bbb", "ccc"};
i = 1;
var[ names[[i]] ] = Sqrt[2]; (* dummy first assignment *)
var[ names[[i]] ] = {1, 2, 3, 4, 5};
var["aaa"]
{1, 2, 3, 4, 5}
In passing, depending on your application you may find Rules applicable.
Forcing the behavior
Suppose you need the behavior you asked for to keep a large program working without extensive modification.
Method #1
This works because Part preserves the head of the expression, here Unevaluated.
Ignore the syntax highlighting in Unevaluated: this is a nonstandard but safe use.
This could easily use the same syntax as Method #2: assign[symbols_, idx_, val_] :=
ClearAll[aaa, bbb, ccc, assign]
assign[idx_, val_] := (# = val) & @ symbols[[1, {idx}]]
symbols = Hold @ Unevaluated[aaa, bbb, ccc];
assign[1, "dummy"];
assign[1, Range@5];
aaa
{1, 2, 3, 4, 5}
Method #2
This uses the injector pattern in preference to Unevaluated.
ClearAll[aaa, bbb, ccc, f1, assign]
assign[symbols_, idx_, val_] := symbols[[{idx}]] /. _[x_] :> (x = val)
symbols = Hold[aaa, bbb, ccc];
assign[symbols, 1, "dummy"];
assign[symbols, 1, Range@5];
aaa
{1, 2, 3, 4, 5}