The i variable is the problem here. When setTimeout finally runs, the loop is already finished. So i is always the last value. You can fix this by changing var i to let i. let creates a new i for each loop turn, so the closure works correctly.
function runTasks(tasks, delay) {
for (let i = 0; i < tasks.length; i++) {
setTimeout(function() {
tasks[i]();
}, delay * i);
}
}