Problems with \foreach aside, I think the syntax
\path (b) edge (d)
(a) edge (b) edge (c) edge (d);
comes much more natural. It is also much easier to change edge options on an edge-to-edge basis (or for more than one edge, too):
\path (b) edge (d) {[thick]
(a) edge (b) edge[green] (c) edge[red,->] (d)};
Though, a similar thing can still be done with \foreach, say
\path (b) edge (d) {[thick]
(a) \foreach \opt/\p in {/b, green/c, {red,->}/d}
{edge[style/.expand once=\opt] (\p)}};
With my qrr.misc library (code similar to the keys in another answer of mine), one can do
\path (b) edge (d) {[thick]
(a) [edges to={b,[green] c, [{red,->}] d}]};
It should be noted that the , in the options has to be protected somehow, either in that way shown or by doing {[red, ->] d}, i.e. enclosing the whole thing in braces. (This could be made more robust or can be changed to use ( and ) around the coordinates instead of using ,, but the implementation will need more parsing then.)
Code
\documentclass[tikz]{standalone}
\usetikzlibrary{qrr.misc}
\begin{document}
\begin{tikzpicture}
\node (a) at (0, 1) {}; \node (b) at (0, -1) {};
\node (c) at (1, 0) {}; \node (d) at (-1, 0) {};
\path (b) edge (d) {[thick]
(a) edge (b) edge[green] (c) edge[red,->] (d)};
\end{tikzpicture}
\begin{tikzpicture}
\node (a) at (0, 1) {}; \node (b) at (0, -1) {};
\node (c) at (1, 0) {}; \node (d) at (-1, 0) {};
\path (b) edge (d) {[thick]
(a) \foreach \opt/\p in {/b, green/c, {red,->}/d}
{edge[style/.expand once=\opt] (\p)}};
\end{tikzpicture}
\begin{tikzpicture}
\node (a) at (0, 1) {}; \node (b) at (0, -1) {};
\node (c) at (1, 0) {}; \node (d) at (-1, 0) {};
\path (b) edge (d) {[thick]
(a) [edges to={b,[green] c, [{red,->}] d}]};
\end{tikzpicture}
\end{document}
Output
