$VAR1 = [
{
'Z' => '5',
'Y' => '4'
},
$VAR1->[0]
];
The second element refers to the first element of the array reference. If $Data::Dumper::Deepcopy = 1;, then you will see that both array elements are the same.
The problem is of variable scoping; see Coping with Scoping. I will try to explain but do wait for better|clearer explanation.
Without my function, the hash %rec has scope file-wide (outside of the loop). The reference to the hash refers to that hash, the only copy. So modifying the only copy of the hash overwrites previous values (see by for { ... } print Dumper( \%rec ) ;). As the reference to the hash is saved twice, same values are repeated in Dumper() output.
Use of my function inside the while loop limits the scope of %rec within the loop. On each iteration a *spanking new* hash is allocated, saving the values as references to each separate hash in the array as expected.