Agree, the ... syntax feels confusing when each fn($x) in the example uses $x as the name of its argument.
My initial instinct would be to write like this:
`$result = $arr
|> fn($arr) => array_column($arr, 'tags') // Gets an array of arrays
|> fn($cols) => array_merge(...$cols)`
Which makes me wonder how this handles scope. I'd imagine the interior of some chained function can't reference the input $arr, right? Does it allow pass by reference?