Почему говорят что forEach меняет начальный массив, если он ничего не меняет?
Не меняется, т.к. а - это значение элемента массива. Но если бы это была ссылка на значение (на объект например), то менялось бы.arr = [{a: 1}, {a: 2}, {a: 3}]; 
arr.forEach(a => {
  a.a++;
})
console.log(arr) // [{a: 2}, {a: 3}, {a: 4}]
В таком случае да, значения объектов поменяются. Но если вы измените ссылку, то нифигаarr = [{a: 1}, {a: 2}, {a: 3}];
arr.forEach(a => {
  a = { a: a.a+1 };
})
console.log(arr) // Тут все по старому
Также, можно поменять значение массива по ключу.arr = [1,2,3]
arr.forEach((a, ind) => {
  arr[ind]++;
})
console.log(arr) // [2,3,4]
В вашем примере, где массив содержит элементы примтивного типа Number, в функцию передаётся значение. Изменение внутри функции не распространяется на изменение в массиве.
Если бы в функцию передавались объекты, передача была бы «по ссылке» и изменения в эти объекты отразились бы сразу в массиве.
В вашем примере можно задействовать два других параметра: индекс элемента и сам массив и явно поменять элементы массива:arr = [1,2,3]
arr.forEach((a,i, theArr) => {
  a = a + 1 ;
  theArr[i] = a;
})
console.log(arr) // [2,3,4]
Поробнее про передачу by value / by reference на англ. на SO. Пример оттуда:function changeStuff(a, b, c)
{
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);        // 10
console.log(obj1.item);  // changed   
console.log(obj2.item);  // unchanged