Can be done in several ways:
n = 5
RepeatedTiming[f1 = Tuples[Range[n], 2];, 0.5]
RepeatedTiming[f2 = Join @@ Array[List, {n, n}];, 0.5]
RepeatedTiming[f3 = Join @@ Table[{i, j}, {i, n}, {j, n}];, 0.5]
RepeatedTiming[f4 = Join @@ Outer[List, Range[n], Range[n]];, 0.5]
RepeatedTiming[f5=Flatten[{ConstantArray[Range[n],n],Transpose[ConstantArray[Range[n],n]]},{{3,2},{1}}];,0.5]
f1 == f2 == f3 == f4==f5
Developer`PackedArrayQ /@ {f1, f2, f3, f4,f5}
f1
Tuples, Outer, and ConstantArray return a packed array which can be faster. Note that Tuples can only return a 'flattened' list of pairs, while the other 3 can provide multiple levels if you need that (that is why I flatten those dimensions out using Join @@).
EDIT:
@Paul @Henrik Did not see you answers yet, next time I should refresh...
EDIT2:
I added a fifth method
EDIT3: You could even do this method (definitely not recommended):
n = 15
col = {}; While[Length[col] < n^2, new = RandomInteger[{1, n}, 2]; col = Union[col, {new}]]
col