Order of evaluation in application/tuple/...?

Not quite. There are a lot of code that have side effects that are observable, but for which the order does not matter. The simplest example is presumably

let fresh = let x = ref 0 in fun () -> let y = !x in x := y + 1; y

More often than not, the callers of this function do not care which integer they get. They only care that the one they get is different from all the other ones. So, the order of the calls does not matter.

But, if you now invoke this function twice in parallel (rather than sequentially), then all hell breaks loose. Parallelization brings a whole new class of bugs (data races, as you explained) that simply do not exist with unspecified order of argument evaluation.

Another example is a memoizing function. It has side effects, but the order of evaluation does not matter. However, data races certainly do.