Consider a function `f` and a list `p={a,b,c}`. I want to get a list of f[a,a] f[a,b] f[a,c] f[b,a] f[b,b] f[b,c] f[c,a] f[c,b] f[c,c] In real use, `p` can have higher dimensions, and f may take more arguments, e.g. I may need to generate a list of `f[a,a,a,a]` through `f[z,z,z,z]`. Is there a cleaner way to do this other than making lists that approximately repeat the elements of `p` then use `MapThread`? e.g. ``` p={a,b} p1 = {a, a, b, b} (* or: p1 = {p, p}\[Transpose] // Flatten *) p2 = {a, b, a, b} (* or: p2 = {p,p}//Flatten *) MapThread[f, {p1, p2}] ```